package com.example.demomk.ViewModel;

import static com.example.demomk.db.AppDatabase.databaseWriteExecutor;

import android.app.Application;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.example.demomk.Dao.AvgMeasurementDao;
import com.example.demomk.Dao.LocationDao;
import com.example.demomk.Dao.MeasurementDao;
import com.example.demomk.Dao.UserDao;
import com.example.demomk.Utils.StatRow;
import com.example.demomk.db.AppDatabase;
import com.example.demomk.entity.AllCount;
import com.example.demomk.entity.AvgMeasurement;
import com.example.demomk.entity.AvgMeasurementWithDetails;
import com.example.demomk.entity.AvgMeasurementWithMeasurements;
import com.example.demomk.entity.Location;
import com.example.demomk.entity.LocationStats;
import com.example.demomk.entity.Measurement;
import com.example.demomk.entity.MeasurementSummary;
import com.example.demomk.entity.SizeStats;
import com.example.demomk.entity.User;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class MeasurementViewModel extends AndroidViewModel {

    private final MutableLiveData<List<MeasurementSummary>> _summaryList = new MutableLiveData<>();
    public LiveData<List<MeasurementSummary>> summaryList = _summaryList;


    private final MeasurementDao measurementDao;
    private final UserDao userDao;
    private final LocationDao locationDao;
    private final AvgMeasurementDao avgMeasurementDao;
    private final MutableLiveData<Map<Integer, List<Measurement>>> measurementsMap = new MutableLiveData<>(new HashMap<>());


    public interface StatsCallback {
        void onStatsCalculated(List<SizeStats> stats);
    }


    public MeasurementViewModel(@NonNull Application application) {
        super(application);
        AppDatabase db = AppDatabase.getInstance(application);
        measurementDao = db.measurementDao();
        userDao = db.userDao();
        locationDao = db.locationDao();
        avgMeasurementDao = db.avgMeasurementDao();
    }

    //打印数据
    public void loadSummaries(List<Integer> ids) {
        List<MeasurementSummary> result = new ArrayList<>();
        for (Integer id : ids) {
            getMeasurementSummary(id).observeForever(summary -> {
                if (summary != null) {
                    result.add(summary);
                    _summaryList.postValue(result); // 实时更新
                }
            });
        }
    }

    //统计数据
    public void calculateStatsForAvgAsync(AvgMeasurement avg, StatsCallback callback) {
        AppDatabase.databaseWriteExecutor.execute(() -> {
            List<Measurement> measurements = measurementDao.getMeasurementsByUserId(avg.getId());

            List<SizeStats> statsList = new ArrayList<>();

            // 为每个粒径字段分别调用
            processSizeGroup("0.5", measurements, Measurement::getValue05, statsList);
            processSizeGroup("1.0", measurements, Measurement::getValue10, statsList);
            processSizeGroup("2.0", measurements, Measurement::getValue20, statsList);
            processSizeGroup("3.0", measurements, Measurement::getValue30, statsList);
            processSizeGroup("5.0", measurements, Measurement::getValue50, statsList);
            processSizeGroup("10.0", measurements, Measurement::getValue100, statsList);

            // 回到主线程更新 UI
            new Handler(Looper.getMainLooper()).post(() -> callback.onStatsCalculated(statsList));
        });
    }

    private void addValue(Map<String, List<Double>> map, String key, double value) {
        map.computeIfAbsent(key, k -> new ArrayList<>()).add((double) value);
    }
    //局部(点位)最大平均值
    private double calculateMaxLocationAvg(
            List<Measurement> measurements,
            Function<Measurement, Integer> extractor,
            double maxValue) {

        // 按点位分组
        Map<String, List<Double>> measurementsByNote = new HashMap<>();
        for (Measurement m : measurements) {
            String note = m.getNotes();
            if (note != null && !note.isEmpty()) {
                double val = extractor.apply(m);
                addValue(measurementsByNote, note, val);
            }
        }

        // 找出包含最大值的点位
        List<String> maxNoteKeys = new ArrayList<>();
        for (Map.Entry<String, List<Double>> entry : measurementsByNote.entrySet()) {
            if (entry.getValue().contains(maxValue)) {
                maxNoteKeys.add(entry.getKey());
            }
        }

        if (!maxNoteKeys.isEmpty()) {
            String maxNoteKey = maxNoteKeys.get(0);
            List<Double> maxNoteValues = measurementsByNote.get(maxNoteKey);
            return maxNoteValues.stream()
                    .mapToDouble(Double::doubleValue)
                    .average()
                    .orElse(0.0);
        }

        return 0.0;
    }

    private void processSizeGroup(
            String sizeName,
            @NonNull List<Measurement> measurements,
            Function<Measurement, Integer> extractor,
            List<SizeStats> statsList) {

        Map<String, List<Double>> groupedData = new HashMap<>();

        for (Measurement m : measurements) {
            addValue(groupedData, sizeName, extractor.apply(m));
        }

        for (Map.Entry<String, List<Double>> entry : groupedData.entrySet()) {
            String key = entry.getKey();
            List<Double> values = entry.getValue();

            if (!values.isEmpty()) {
                double sum = 0;
                for (double v : values) {
                    sum += v;
                }
                int count = values.size();
                double avgVal = sum / count;
                double max = Collections.max(values);

                double sd = Math.sqrt(values.stream().mapToDouble(v -> Math.pow(v - avgVal, 2)).sum() / (count - 1));
                double se = sd / Math.sqrt(count);

                // 找出最大值所在的点位并计算其平均值
                double maxLoc = calculateMaxLocationAvg(measurements, extractor, max);

                double roundedAvg = Math.round(avgVal * 10) / 10.0;
                double roundedSd = Math.round(sd * 10) / 10.0;
                double roundedSe = Math.round(se * 10) / 10.0;
                double roundedMaxLoc = Math.round(maxLoc * 10) / 10.0;

                statsList.add(new SizeStats(key, values.size(), max, roundedAvg, roundedSd, roundedSe, roundedMaxLoc));
            }
        }
    }
    //以上是统计数据方法

    //点位统计方法
    public LiveData<List<LocationStats>> getLocationStatsByAvgId(int avgId) {
        MutableLiveData<List<LocationStats>> result = new MutableLiveData<>();

        AppDatabase.databaseWriteExecutor.execute(() -> {
            List<Measurement> measurements = measurementDao.getMeasurementsByUserId(avgId);

            // 按 note 分组
            Map<String, List<Measurement>> groupedByNote = new HashMap<>();
            for (Measurement m : measurements) {
                groupedByNote.computeIfAbsent(m.getNotes(), k -> new ArrayList<>()).add(m);
            }

            List<LocationStats> statsList = new ArrayList<>();

            for (Map.Entry<String, List<Measurement>> entry : groupedByNote.entrySet()) {
                String note = entry.getKey();
                List<Measurement> list = entry.getValue();

                int count = list.size();

                double avg05 = list.stream().mapToDouble(Measurement::getValue05).average().orElse(0.0);
                double avg10 = list.stream().mapToDouble(Measurement::getValue10).average().orElse(0.0);
                double avg20 = list.stream().mapToDouble(Measurement::getValue20).average().orElse(0.0);
                double avg30 = list.stream().mapToDouble(Measurement::getValue30).average().orElse(0.0);
                double avg50 = list.stream().mapToDouble(Measurement::getValue50).average().orElse(0.0);
                double avg100 = list.stream().mapToDouble(Measurement::getValue100).average().orElse(0.0);

                double flow = list.stream().mapToDouble(Measurement::getFlowRate).average().orElse(0.0);
                statsList.add(new LocationStats(note, count, avg05, avg10, avg20, avg30, avg50, avg100,flow));

            }
            Collections.sort(statsList, (o1, o2) -> o1.getLocationName().compareTo(o2.getLocationName()));
            result.postValue(statsList);
        });

        return result;
    }



    public User getUserByName(String name) {
        return userDao.findUserByName(name);
    }

    public LiveData<List<User>> getAllUsers() {
        return userDao.getAllUsers();
    }
    public void insertUser(User user) {
        databaseWriteExecutor.execute(() -> {
            userDao.insertUser(user);
        });

    }
    //Location
    public LiveData<List<Location>> getAllLocations() {
        return locationDao.getAllLocations();
    }
    public void insertLocation(Location location) {
        databaseWriteExecutor.execute(() -> {
            locationDao.insertLocation(location);
        });
    }

    public Location getLocationByName(String name) {
        return locationDao.findLocationByName(name);
    }

    //插入用户单条记录
    public void insertAvgMeasurement(AvgMeasurement measurement) {
        databaseWriteExecutor.execute(() -> {
            avgMeasurementDao.insertAvgMeasurement(measurement);
        });
    }

    //删除记录
    public void deleteMeasurement(Measurement measurement) {
        databaseWriteExecutor.execute(() -> {
            measurementDao.deleteMeasurement(measurement);
        });
    }
    //删除表
    public void deleteAllMeasurements() {
        databaseWriteExecutor.execute(() -> {
            measurementDao.deleteAllMeasurements();
        });
    }
    public void addNewMeasurement( int parentId, String startTime, String endTime,
                                  double flowRate,int  value03, int value05, int value10,
                                   int value20, int value30,int value50 , int value100, String Location) {
        AppDatabase.databaseWriteExecutor.execute(() -> {
            Measurement measurement = new Measurement(parentId);
            measurement.setStartTime(startTime);
             // 简单处理，结束时间=开始时间的日期部分
            measurement.setEndTime(startTime.substring(0, 10));
            measurement.setFlowRate(flowRate);
            measurement.setValue03(value03);
            measurement.setValue05(value05);
            measurement.setValue10(value10);
            measurement.setValue20(value20);
            measurement.setValue30(value30);
            measurement.setValue50(value50);
            measurement.setValue100(value100);

            measurement.setNotes(Location);

            measurementDao.insertMeasurement(measurement);
        });
    }
//
//    //查询全部
//    public LiveData<List<MeasurementWithDetails>> getAllMeasurement() {
//        return measurementDao.getAllMeasurement();
//    }
//
//

//
//    public LiveData<List<MeasurementWithDetails>> getMeasurementDetails(int measurementId) {
//        return measurementDao.getMeasurementDetails(measurementId);
//    }
//

//    //按用户id查询记录
////    public LiveData<List<Measurement>> getMeasurementsByUser(int userId) {
////        return measurementDao.getMeasurementsByUser(userId);
////    }
//

//查询总数
    public LiveData<Integer> getMeasurementCount() {
        return measurementDao.getMeasurementCount();
    }

    //查询用户记录
    public LiveData<List<AvgMeasurementWithDetails>>  getAllAvgMeasurements() {
        return avgMeasurementDao.getAllAvgMeasurements();
    }

    //校验查询
    public  LiveData<Integer> isExist(int userId,  int locationId) {
        return avgMeasurementDao.isExist(userId,  locationId);
    }
    //获取用户下的数据
    public LiveData<AvgMeasurementWithMeasurements> getAvgMeasurementWithDetails(int avgId) {
        return avgMeasurementDao.getAvgMeasurementWithDetails(avgId);
    }
    //返回一个
    public LiveData<AvgMeasurementWithDetails> getAllAvgMeasurementId(int id) {
        return avgMeasurementDao.getAllAvgMeasurementId(id);
    }

    //查询所有
    public LiveData<List<AllCount>> getAllAvg() {
        return avgMeasurementDao.getAllAvg();
    }

    //getAvgDetails
    public LiveData<List<AvgMeasurementWithMeasurements>> getAvgDetails() {
        return avgMeasurementDao.getAvgDetails();
    }


    //新增
    public void loadMeasurementDetails(int avgMeasurementId) {
//        Log.d("MeasurementVM", "开始加载详情: " + avgMeasurementId);
        avgMeasurementDao.getAvgMeasurementWithDetails(avgMeasurementId).observeForever(measurements -> {
//            Log.d("MeasurementVM", "获取到详情数据: " + avgMeasurementId + ", 数量: " + (measurements != null ? measurements.measurements.size() : 0));
            Map<Integer, List<Measurement>> currentMap = measurementsMap.getValue();
            if (currentMap == null) {
                currentMap = new HashMap<>();
            }
            currentMap.put(avgMeasurementId, measurements.measurements);
            measurementsMap.setValue(currentMap);
        });
    }

    public LiveData<Map<Integer, List<Measurement>>> getMeasurementsMap() {
        return measurementsMap;
    }

    //测试分页
    public LiveData<List<AvgMeasurementWithDetails>> getAllAvgNext(long lastId, int limit) {
        return avgMeasurementDao.getAllAvgNext(lastId,limit);
    }

    //avg总数
    public LiveData<Integer> getAvgMeasurementCount() {
        return avgMeasurementDao.getAvgMeasurementCount();
    }

    //查询当前打印的信息
    public LiveData<MeasurementSummary> getMeasurementSummary(int avgId) {
        return avgMeasurementDao.getMeasurementSummary(avgId);
    }

    public List<Measurement> getMeasurementsByUserId(int avg_id){
        return  measurementDao.getMeasurementsByUserId(avg_id);
    }

    //avg表根据id查询
    public LiveData<List<AvgMeasurement>> getAvgMeasurementById(int id) {
        return avgMeasurementDao.getAvgMeasurementById(id);
    }
}